package com.wzdigit.wms.raw.service.asn;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicDataItemDetailApi;
import com.wzdigit.mes.basic.api.BasicSimpleCodeRuleApi;
import com.wzdigit.mes.basic.api.BasicVendorApi;
import com.wzdigit.mes.basic.api.QrCodeParseRulesApi;
import com.wzdigit.mes.basic.dto.DataItemDetailDTO;
import com.wzdigit.mes.basic.dto.VendorDTO;
import com.wzdigit.mes.qms.api.InspectionGroupApi;
import com.wzdigit.mes.qms.api.InspectionListApi;
import com.wzdigit.mes.qms.dto.InspectionGroupStaffDto;
import com.wzdigit.wms.basic.client.Pager;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.domain.asn.AsnDtl;
import com.wzdigit.wms.basic.domain.asn.AsnDtlGoods;
import com.wzdigit.wms.basic.domain.asn.AsnHeader;
import com.wzdigit.wms.basic.domain.basic.Sku;
import com.wzdigit.wms.basic.domain.basic.Warehouse;
import com.wzdigit.wms.basic.domain.dtos.basic.QrGoodsDto;
import com.wzdigit.wms.basic.domain.dtos.inventory.UpdateInventoryInputDto;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.inventory.GoodsLog;
import com.wzdigit.wms.basic.domain.order.TrsnDtl;
import com.wzdigit.wms.basic.domain.order.TrsnDtlGoods;
import com.wzdigit.wms.basic.domain.order.TrsnHeader;
import com.wzdigit.wms.basic.domain.qms.QmsIqc;
import com.wzdigit.wms.basic.domain.qms.QmsOqcRcard;
import com.wzdigit.wms.basic.enums.*;
import com.wzdigit.wms.basic.mapper.core.basic.SkuMapper;
import com.wzdigit.wms.basic.mapper.core.basic.WarehouseMapper;
import com.wzdigit.wms.basic.mapper.core.inventory.GoodsLogMapper;
import com.wzdigit.wms.basic.mapper.core.inventory.GoodsMapper;
import com.wzdigit.wms.basic.mapper.core.order.TrsnDtlGoodsMapper;
import com.wzdigit.wms.basic.mapper.core.order.TrsnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.order.TrsnHeaderMapper;
import com.wzdigit.wms.basic.mapper.core.qms.QmsIqcMapper;
import com.wzdigit.wms.basic.mapper.core.qms.QmsOqcRcardMapper;
import com.wzdigit.wms.basic.service.SkuPermService;
import com.wzdigit.wms.basic.service.code.InventoryService;
import com.wzdigit.wms.basic.service.code.QrCodeParsingService;
import com.wzdigit.wms.basic.service.code.RedisService;
import com.wzdigit.wms.basic.service.code.WhsPermService;
import com.wzdigit.wms.basic.util.DateUtils;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.basic.util.WrapperUtil;
import com.wzdigit.wms.basic.util.common.LockNumber;
import com.wzdigit.wms.basic.util.enums.SystemModuleEnum;
import com.wzdigit.wms.raw.client.request.asn.receive.AddAsnDtlGoodsReceiveRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.ConfirmAsnDtlGoodsReceiveRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.ConfirmAsnDtlGoodsReceiveRequest.ConfirmAsnDtlGoodsReceiveItemRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.RemoveAsnDtlGoodsReceiveRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.SearchAsnDtlGoodsReceiveRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.SearchAsnDtlReceiveRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.SearchAsnHeaderReceiveRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.UpdateAsnDtlQtyReceiveRequest;
import com.wzdigit.wms.raw.client.request.asn.receive.UpdateAsnDtlWhsRequest;
import com.wzdigit.wms.raw.client.response.asn.receive.AsnDtlGoodsReceiveResponse;
import com.wzdigit.wms.raw.client.response.asn.receive.AsnDtlReceiveResponse;
import com.wzdigit.wms.raw.client.response.asn.receive.AsnHeaderReceiveResponse;
import com.wzdigit.wms.raw.domain.dto.PreAsnReceiveDtlDto;
import com.wzdigit.wms.raw.domain.dto.CanRemoveAsnDtlGoodsReceiveDto;
import com.wzdigit.wms.raw.exception.SystemException;
import com.wzdigit.wms.raw.mapper.asn.AsnReceiveDtlGoodsMapper;
import com.wzdigit.wms.raw.mapper.asn.AsnReceiveDtlMapper;
import com.wzdigit.wms.raw.mapper.asn.AsnReceiveHeaderMapper;
import com.wzdigit.wms.raw.service.backtosap.*;
import com.wzdigit.wms.raw.service.mid.MappingHouseService;
import com.wzdigit.wms.web.service.common.wms2sap.ZDT_Reserve;
import com.wzdigit.wms.web.service.wms2sap.waitcheckinstore.ZDT_064_ReqRECORDS;
import com.wzdigit.wms.web.service.wms2sap.wmsbillstatus.ZDT_076_ReqItems;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import org.apache.axis.schema.SchemaVersion1999;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 *
 * 收料入库服务
 * @author Administrator
 *
 */
@Service
@Slf4j
public class AsnReceiveService {

	@Autowired
	WarehouseMapper warehouseMapper;
	@Autowired
	private SkuMapper skuMapper;

	@Autowired
	private GoodsMapper goodsMapper;

	@Autowired
	private GoodsLogMapper goodsLogMapper;

	@Autowired
	private AsnReceiveDtlMapper asnDtlMapper;

	@Autowired
	private AsnReceiveHeaderMapper asnHeaderMapper;

	@Autowired
	private AsnReceiveDtlGoodsMapper asnDtlGoodsMapper;

	@Autowired
	private TrsnHeaderMapper trsnHeaderMapper;

	@Autowired
	private QmsIqcMapper qmsIqcMapper;

	@Autowired
	private QmsOqcRcardMapper qmsOqcRcardMapper;

	@Autowired
	private TrsnDtlMapper trsnDtlMapper;

	@Autowired
	private TrsnDtlGoodsMapper trsnDtlGoodsMapper;

	@Autowired
	private InventoryService inventoryService;

	@Autowired
	private SkuPermService skuPermService;

	@Autowired
	private WhsPermService whsCodeService;

	@Autowired
	private MappingHouseService mappingHouseService;

	@Autowired
	private WaitCheckBackService waitCheckBackService;

	@Autowired
	private GetAndReturnMaterialBackService getAndReturnMaterialBackService;

	@Autowired
	private OutStoreBackService outStoreBackService;

	@Autowired
	private WmsBillStatusBackService wmsBillStatusBackService;

	@Autowired
	private QrCodeParsingService qrCodeParsingService;

	@Autowired
	private RedisService redisService;

	@Reference(version = "${dubbo.consumers.basic.qrCodeParseRules.api:1.0.0}", check = false, timeout = 300000)
	private QrCodeParseRulesApi qrCodeParseRulesApi;

	@Reference(version = "${dubbo.consumers.basic.simple.code.rule.api:1.0.0}", check = false,retries = 0)
	private BasicSimpleCodeRuleApi basicSimpleCodeRuleApi;

	@Reference(version = "${dubbo.consumers.vendor.api:1.0.0}", check = false)
	private BasicVendorApi basicVendorApi;

	@Reference(version = "${dubbo.consumers.qms.InspectionGroupApi.api:1.0.0}", check = false)
	private InspectionGroupApi inspectionGroupApi;

	@Reference(version = "${dubbo.consumers.qms.InspectionListApi.api:1.0.0}", check = false)
	private InspectionListApi inspectionListApi;

	@Reference(version = "${dubbo.consumers.basic.data.item.detail.api:1.0.0}", check = false, timeout = 300000)
	private BasicDataItemDetailApi dataItemDetailApi;

	private static final String IQC_INSP_ORDER_NO = "IQCInspOrderNo";	// 创建送检单单号编码
	private static final String TRSN_ORDER = "TRSN_ORDER";				// 创建凭证编码
	private static final String INSPECTION_GROUP_TYPE = "13";			// 检验组类型=来料检验
	private static final String INSP_MODE = "INSP_MODE";				// 默认的送检方式数据字典编码

	/**
	 * 主档查询
	 *
	 * @param dto
	 * @param pager
	 * @param servletRequest
	 * @return
	 *
	 * WW.WHS_TYPE = 1（原材料仓）
	 * WAH.STATUS = 1（新建）, 2（部分收货）, 3（完全收货）, 4（完成）
	 * WAH.ASN_TYPE = R11（生产退料）, R12（委外退料）, R13（VIM入库）,R14（入库单）
	 */
	public PagerInfo<List<AsnHeaderReceiveResponse>> searchAsnHeaderReceive(
			SearchAsnHeaderReceiveRequest dto, Pager<?> pager,
			HttpServletRequest servletRequest) {
		Date beginDate = null, endDate = null;
		if(dto.getBeginTime() != null) {
			beginDate = DateUtils.getStartTime(dto.getBeginTime());
			endDate = DateUtils.getEndTime(dto.getBeginTime());
		}

		String userName = HttpSessionUtil.getLoginName(servletRequest);

		// 当前用户权限的仓库
		List<Integer> whsIdList = whsCodeService.getWareHouseIds(userName);

		// 单据类型
		List<String> asnTypeList = AsnTypeEnum.getEnumBySystemModule(SystemModuleEnum.RAW);

		// 当前用户权限的物料
		List<Integer> skuIdList = null;

		if (dto.getIsOneselfPerm() != null && dto.getIsOneselfPerm()) {
			/*GetUserWhsZoneWorkDivisionDto apiDto = new GetUserWhsZoneWorkDivisionDto();
			apiDto.setWorkDivisionType(WorkDivisionTypeEnum.WO.code);
			apiDto.setUserName(userName);

			// 当前用户工作权限分工
			List<UserWhsZoneWorkDivisionResponse> workDivisionList = userWorkDivisonMapper.getUserWhsZoneWorkDivision(apiDto);
			if(workDivisionList.size() > 0) {
				List<Integer> workDivisionIdList = workDivisionList.stream().map(w -> w.getWorkDivisionDtlId()).collect(Collectors.toList());

				// 当前用户负责的物料ID集合
				List<WorkDivisionExtSku> workDivisionExtSkuList = workDivisionExtSkuMapper.selectByWorkDivisionDtlIdList(workDivisionIdList);
				skuIdList = workDivisionExtSkuList.stream().map(s -> s.getSkuId()).collect(Collectors.toList());
			} else {
				skuIdList = new ArrayList<>(0);
			}*/

			// 2021/08/17调整仓管员获取方式，从SAP同步接口获取。
			skuIdList = skuPermService.getSkuIdPerm(userName, whsIdList);
		}

		Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
		PagerInfo<List<AsnHeaderReceiveResponse>> pagerInfo = new PagerInfo<>();
		List<AsnHeaderReceiveResponse> list = asnHeaderMapper.selectReceive(dto, asnTypeList, whsIdList, skuIdList, beginDate, endDate);
		pagerInfo.setItems(list);
		pagerInfo.setTotalCount(page.getTotal());
		return pagerInfo;
	}

	/**
	 * 明细查询
	 *
	 * @param dto
	 * @return
	 *
	 * WW.WHS_TYPE = 1（原材料仓）
	 */
	public List<AsnDtlReceiveResponse> searchAsnDtlReceive(SearchAsnDtlReceiveRequest dto, HttpServletRequest servletRequest) {
		String userName = HttpSessionUtil.getLoginName(servletRequest);

		// 当前用户权限的仓库
		List<Integer> whsIdList = whsCodeService.getWareHouseIds(userName);

		// 当前用户权限的物料
		List<Integer> skuIdList = null;

		if (dto.getIsOneselfPerm() != null && dto.getIsOneselfPerm()) {
			/*GetUserWhsZoneWorkDivisionDto apiDto = new GetUserWhsZoneWorkDivisionDto();
			apiDto.setWorkDivisionType(WorkDivisionTypeEnum.WO.code);
			apiDto.setUserName(userName);

			// 当前用户工作权限分工
			List<UserWhsZoneWorkDivisionResponse> workDivisionList = userWorkDivisonMapper.getUserWhsZoneWorkDivision(apiDto);
			if(workDivisionList.size() > 0) {
				List<Integer> workDivisionIdList = workDivisionList.stream().map(w -> w.getWorkDivisionDtlId()).collect(Collectors.toList());

				// 当前用户负责的物料ID集合
				List<WorkDivisionExtSku> workDivisionExtSkuList = workDivisionExtSkuMapper.selectByWorkDivisionDtlIdList(workDivisionIdList);
				skuIdList = workDivisionExtSkuList.stream().map(s -> s.getSkuId()).collect(Collectors.toList());
			} else {
				skuIdList = new ArrayList<>(0);
			}*/

			//2021/08/17调整仓管员获取方式，从SAP同步接口获取。
			skuIdList = skuPermService.getSkuIdPerm(userName, whsIdList);
		}

		List<AsnDtlReceiveResponse> list = asnDtlMapper.selectReceive(dto, whsIdList, skuIdList);
		return list;
	}

	/**
	 * 明细货品清单查询
	 *
	 * @param dto
	 * @return
	 */
	public List<AsnDtlGoodsReceiveResponse> searchAsnDtlGoodsReceive(SearchAsnDtlGoodsReceiveRequest dto) {
		List<AsnDtlGoodsReceiveResponse> list = asnDtlGoodsMapper.selectReceive(dto);
		return list;
	}

	/**
	 * 更新收货单物料仓库
	 *
	 * @param dto
	 * @param servletRequest
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<?> updateAsnDtlWhs(UpdateAsnDtlWhsRequest dto, HttpServletRequest servletRequest) {
		// 收货单表头
		AsnHeader asnHeader = asnHeaderMapper.selectById(dto.getAsnHeaderId());
		if (!Objects.equals(asnHeader.getStatus(), AsnHeaderStatusEnum.CREATE.code)) {
			Shift.fatal(String.format("当前送货单状态为【%s】，不允许变更仓库，只有【新建】状态才可以变更！",
					AsnHeaderStatusEnum.getEnumByCode(asnHeader.getStatus()).enumName));
		}

		// 用户名、当前时间
		String loginName = HttpSessionUtil.getLoginName(servletRequest);
		Date date = new Date();

		AsnDtl asnDtl = new AsnDtl();
		asnDtl.setWhsId(dto.getWhsId());
		asnDtl.setModifyTime(date);
		asnDtl.setModifyUser(loginName);

		QueryWrapper<AsnDtl> asnDtlQueryWrapper = new QueryWrapper<>();
		// asnDtlQueryWrapper.eq("SKU_ID", dto.getSkuId());
		asnDtlQueryWrapper.eq("ASN_HEADER_ID", dto.getAsnHeaderId());
		asnDtlMapper.update(asnDtl, asnDtlQueryWrapper);
		return new Result<>();
	}

	/**
	 * 清除明细货品清单
	 *
	 * @param dto
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<?> removeAsnDtlGoodsReceive(RemoveAsnDtlGoodsReceiveRequest dto, HttpServletRequest servletRequest) {
		// 收货单表头
		AsnHeader asnHeader = asnHeaderMapper.selectById(dto.getAsnHeaderId());
		log.info("["+asnHeader.getAsnNo()+"]下["+dto.getGoodsSnList().toString());
		if (Objects.equals(asnHeader.getStatus(), AsnHeaderStatusEnum.FINISH.code)) {
			Shift.fatal("当前送货单已完成收货！");
		}

		List<CanRemoveAsnDtlGoodsReceiveDto> canRemoveList = asnDtlGoodsMapper.selectCanRemoveReceiveId(dto);
		if (canRemoveList.size() == 0) {
			Shift.fatal("只有待接收的条码才允许清除！");
		}

		long timeOut = LockNumber.SECONDS_II;//锁过期时间
		String lockKey=dto.getAsnHeaderId()+ "";//锁

		if (redisService.lock(lockKey, timeOut)){
			try {

				List<Integer> asnDtlGoodsIdList = canRemoveList.stream().map(s -> s.getAsnDtlGoodsId()).collect(Collectors.toList());
				List<Integer> goodsIdList = canRemoveList.stream().map(s -> s.getGoodsId()).collect(Collectors.toList());
				List<String> goodsSnList = canRemoveList.stream().map(s -> s.getGoodsSn()).collect(Collectors.toList());

				asnDtlGoodsMapper.deleteBatchIds(asnDtlGoodsIdList);
				goodsMapper.deleteBatchIds(goodsIdList);

				QueryWrapper<GoodsLog> goodsLogQueryWrapper = new QueryWrapper<>();
				goodsLogQueryWrapper.in("GOODS_SN", goodsSnList);
				goodsLogMapper.delete(goodsLogQueryWrapper);

				// 用户名、当前时间
				String loginName = HttpSessionUtil.getLoginName(servletRequest);
				Date date = new Date();

				// 调用SAP接口【清除条码--->单子的所有条码都清除完毕的时候调用】
				int goodsSnSize = asnDtlGoodsMapper.selectCountSnAsn(asnHeader.getAsnHeaderId());
				if (goodsSnSize == 0) {
					try {
						ZDT_076_ReqItems record = new ZDT_076_ReqItems();
						record.setBILLTYPE("1");	// 默认1
						record.setBILLNO(asnHeader.getAsnNo());
						record.setZDATE(DateUtil.format(date, "yyyyMMdd"));
						record.setZTIME(DateUtil.format(date, "HHmmss"));
						record.setSTATUS("2");		// 1确认、2取消
						record.setZNAME(loginName);
						wmsBillStatusBackService.backToSap(record);
					} catch (SystemException e) {
						Shift.fatal(e.getMessage());
					} catch (Exception e) {
						e.printStackTrace();
						Shift.fatal("调用SAP接口失败");
					}
				}
			}catch (Exception e){
				e.printStackTrace();
				throw e;
			}finally {
				//释放锁
				redisService.unlock(lockKey);
			}
		}
		return new Result<>();
	}

	/**
	 * 扫描预收入库
	 *
	 * @param dto
	 * @param servletRequest
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<String> addAsnDtlGoodsReceive(AddAsnDtlGoodsReceiveRequest dto, HttpServletRequest servletRequest) {
		// 收货单表头
		AsnHeader asnHeader = asnHeaderMapper.selectById(dto.getAsnHeaderId());
		if (Objects.equals(asnHeader.getStatus(), AsnHeaderStatusEnum.CANCEL.code)) {
			Shift.fatal("当前送货单已取消收货！");
		}
		if (Objects.equals(asnHeader.getStatus(), AsnHeaderStatusEnum.FINISH.code)) {
			Shift.fatal("当前送货单已完成收货！");
		}

		// 解析goods
		QrGoodsDto qrGoodsDto = qrCodeParsingService.initializeGoodsQrCode(dto.getQrRuleParam());

		// 验证1【条码是否已被扫描】
		QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
		goodsQueryWrapper.eq("GOODS_SN", qrGoodsDto.getGoodsSn());
		if (goodsMapper.selectCount(goodsQueryWrapper) > 0) {
			Shift.fatal("该SN已收料，不可重复收料！");
		}

		// 校验SN是否在源单据出库单下【ZYF】
		if (asnHeader.getAsnType().equals(AsnTypeEnum.R19.code) || asnHeader.getAsnType().equals(AsnTypeEnum.R20.code)) {
			if (asnHeader.getDataSource() != null) {
				List<String> sourceSn = asnDtlGoodsMapper.selectSourceSn(asnHeader.getDataSource());
				if (CollectionUtil.isEmpty(sourceSn)) {
					Shift.fatal("扫描SN不属于来源出库单!");
				}
				if (!sourceSn.contains(qrGoodsDto.getGoodsSn())) {
					Shift.fatal("扫描SN不属于来源出库单!");
				}
			}
		}

		// 验证2【物料条码是否一致】
		if(!Objects.equals(dto.getSkuId(), qrGoodsDto.getSkuId())) {
			QueryWrapper<AsnDtl> asnDtlQueryWrapper = new QueryWrapper<>();
			asnDtlQueryWrapper.eq("SKU_ID", qrGoodsDto.getSkuId());
			asnDtlQueryWrapper.eq("ASN_HEADER_ID", dto.getAsnHeaderId());
			if (asnDtlMapper.selectCount(asnDtlQueryWrapper) > 0) {
				if (dto.getSkuIdList() != null && dto.getSkuIdList().stream().allMatch(t -> !Objects.equals(t, qrGoodsDto.getSkuId()))) {
					Shift.fatal(String.format("没有SN物料编码[%s]的权限，请确认！", qrGoodsDto.getSkuCode()));
				}
				String message = String.format("SN物料编码[%s]与当前选定物料编码[%s]不一致，是否切换物料？", qrGoodsDto.getSkuCode(), dto.getSkuCode());
				return new Result<>(false, message, qrGoodsDto.getSkuCode());
			} else {
				Shift.fatal(String.format("SN物料编码[%s]不在本收货单物料范围内，请确认！", qrGoodsDto.getSkuCode()));
			}
		}

		// 验证3【条码数量是否超支】
		List<PreAsnReceiveDtlDto> preList = asnDtlMapper.selectPreByAsnHeaderIdAndSkuId(dto.getAsnHeaderId(), dto.getSkuId());
		List<PreAsnReceiveDtlDto> canPreList = preList.stream().filter(t -> t.getPreQty().signum() == 1).collect(Collectors.toList());
		if(canPreList.size() == 0) {
			Shift.fatal("该物料已收货/预收已满！");
		} else {
			BigDecimal canPreQty = canPreList.stream().map(t -> t.getPreQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
			if (qrGoodsDto.getQty().compareTo(canPreQty) == 1) {
				Shift.fatal("待确认数+已收数不能超过需求数，请确认后再操作！");
			}
		}

		// 验证4
		if (asnHeader.getOwner() == null) {
			Shift.fatal("收货单的货主为空！");
		}
		if (asnHeader.getFactory() == null) {
			Shift.fatal("收货单的组织代码为空！");
		}
		if (Objects.equals(AsnTypeEnum.R14.code, asnHeader.getAsnType())
				&& !Objects.equals(qrGoodsDto.getVendorId(), asnHeader.getVendorId())) {
			Shift.fatal("SN供应商和收货单供应商不一致！");
		}

		PreAsnReceiveDtlDto firstPre = preList.get(0);
		if (preList.stream().anyMatch(t -> t.getQaStatus() == null)) {
			Shift.fatal("该物料的收货单的品质状态为空！");
		}
		if (preList.stream().anyMatch(t -> t.getWhsId() == null)) {
			Shift.fatal("该物料的收货单的仓库为空！");
		}
		if (preList.stream().anyMatch(t -> !Objects.equals(t.getQaStatus(), firstPre.getQaStatus()))) {
			Shift.fatal("该物料的收货单存在多种的品质状态！");
		}
		if (preList.stream().anyMatch(t -> !Objects.equals(t.getInvAttr(), firstPre.getInvAttr()))) {
			Shift.fatal("该物料的收货单存在多种的库存性质！");
		}
		if (preList.stream().anyMatch(t -> !Objects.equals(t.getWhsId(), firstPre.getWhsId()))) {
			Shift.fatal("该物料的收货单存在多个仓库！");
		}

		// 用户名、当前时间
		String loginName = HttpSessionUtil.getLoginName(servletRequest);
		Date date = new Date();

		// 新增GOODS
		Goods goods = new Goods();
		BeanUtil.copyNonNull(qrGoodsDto, goods);
		goods.setVendorId(null);	// 置空供应商
		goods.setOwner(asnHeader.getOwner());
		goods.setFactory(asnHeader.getFactory());
		goods.setQaStatus(firstPre.getQaStatus());
		goods.setInvAttr(firstPre.getInvAttr());
		goods.setIsHold(0);
		goods.setIsOriginalPackage(1);
		goods.setStatus(GoodsStatusEnum.WAIT_IN.code);
		goods.setSnType(5);			// 外箱条码
		goods.setCreateUser(loginName);
		goods.setCreateTime(date);
		try {
			goodsMapper.insert(goods);
		} catch (DuplicateKeyException e) {
			// 违反SN的唯一索引限制条件
			Shift.fatal("该SN已收料，不可重复收料！");
		}

		// 新增GOODS_LOG
		GoodsLog goodsLog = new GoodsLog();
		goodsLog.setGoodsSn(goods.getGoodsSn());
		goodsLog.setOpCode(OpCodeEnum.CREATE.getCode());
		goodsLog.setReason(OpCodeEnum.CREATE.getEnumName());
		goodsLog.setOperator(OpCodeEnum.CREATE.getEnumName());
		goodsLog.setUpdateContent(JSON.toJSONString(goods));
		goodsLog.setCreateUser(loginName);
		goodsLog.setCreateTime(date);
		goodsLogMapper.insert(goodsLog);

		// 新增WMS_ASN_DTL_GOODS
		BigDecimal goodsQty = goods.getQty();
		for (PreAsnReceiveDtlDto canPre : canPreList) {
			if(goodsQty.signum() == 0) {
				break;
			}
			BigDecimal qty = null;
			if(goodsQty.compareTo(canPre.getPreQty()) == 1) {
				qty = canPre.getPreQty();
				goodsQty = goodsQty.subtract(canPre.getPreQty());
			} else {
				qty = goodsQty;
				goodsQty = BigDecimal.ZERO;
			}
			AsnDtlGoods asnDtlGoods = new AsnDtlGoods();
			asnDtlGoods.setAsnDtlId(canPre.getAsnDtlId());
			asnDtlGoods.setGoodsSn(goods.getGoodsSn());
			asnDtlGoods.setGoodsId(goods.getGoodsId());
			asnDtlGoods.setQaStatus(goods.getQaStatus());
			asnDtlGoods.setQty(qty);
			asnDtlGoods.setStatus(AsnDtlGoodsStatusEnum.WAIT_RECEIVE.code);
			asnDtlGoods.setCreateUser(loginName);
			asnDtlGoods.setCreateTime(date);
			asnDtlGoodsMapper.insert(asnDtlGoods);
		}

		// 调用SAP接口【扫描入库--->当前单子扫进第一个条码的时候调用】
		int goodsSnSize = asnDtlGoodsMapper.selectCountSnAsn(asnHeader.getAsnHeaderId());
		if (goodsSnSize == 1) {
			try {
				ZDT_076_ReqItems record = new ZDT_076_ReqItems();
				record.setBILLTYPE("1"); 	// 默认1
				record.setBILLNO(asnHeader.getAsnNo());
				record.setZDATE(DateUtil.format(date, "yyyyMMdd"));
				record.setZTIME(DateUtil.format(date, "HHmmss"));
				record.setSTATUS("1"); 		// 1确认、2取消
				record.setZNAME(loginName);
				wmsBillStatusBackService.backToSap(record);
			} catch (SystemException e) {
				Shift.fatal(e.getMessage());
			} catch (Exception e) {
				e.printStackTrace();
				Shift.fatal("调用SAP接口失败");
			}
		}
		return new Result<>(dto.getQrRuleParam());
	}


	/**
	 * 确认收货
	 *
	 * @param dto
	 * @param servletRequest
	 * @return
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<?> confirmAsnDtlGoodsReceive(ConfirmAsnDtlGoodsReceiveRequest dto, HttpServletRequest servletRequest) throws Exception {
		long timeOut = LockNumber.SECONDS_II;//锁过期时间
		String lockKey=dto.getAsnHeaderId()+ "";//锁
		if (redisService.lock(lockKey, timeOut)){
			try{
				// 【行级锁】控制到每个收货单
				QueryWrapper<AsnHeader> lockWrapper = WrapperUtil.lock(AsnHeader.class);
				lockWrapper.eq("ASN_HEADER_ID", dto.getAsnHeaderId());
				AsnHeader asnHeader = asnHeaderMapper.selectOne(lockWrapper);

				if (Objects.equals(asnHeader.getStatus(), AsnHeaderStatusEnum.CANCEL.code)) {
					Shift.fatal("当前送货单已取消收货！");
				}
				if (Objects.equals(asnHeader.getStatus(), AsnHeaderStatusEnum.FINISH.code)) {
					Shift.fatal("当前送货单已完成收货！");
				}

				// 默认的送检方式ID和编码
				DataItemDetailDTO inspMode = dataItemDetailApi.getDataItemDetailByPCodeAndName(INSP_MODE, "来料检验");

				// 供应商
				VendorDTO vendor = basicVendorApi.getVendorById(asnHeader.getVendorId());
                //仓库


				// goods条码集合
				Map<Integer, Goods> goodsItemMap = new HashMap<Integer, Goods>();

				// 用户名
				String loginName = HttpSessionUtil.getLoginName(servletRequest);

				// 当前时间
				Date date = new Date();

				// 是否急料【物料分组】
				Map<Integer, Integer> isEmergencyMap = dto.getItemList().stream().collect(Collectors.toMap(
						ConfirmAsnDtlGoodsReceiveItemRequest::getSkuId, ConfirmAsnDtlGoodsReceiveItemRequest::getIsEmergency));

				// 送检单集合
				List<QmsIqc> qmsIqcList = new ArrayList<>();

				// 【定义集合存储需要回传给SAP的信息，详细字段请看接口文档】
				List<ZDT_064_ReqRECORDS> sapReturnList = new ArrayList<>();

				// 收货单明细
				QueryWrapper<AsnDtl> asnDtlQueryWrapper = new QueryWrapper<>();
				asnDtlQueryWrapper.eq("ASN_HEADER_ID", dto.getAsnHeaderId());
				List<AsnDtl> allAsnDtlList = asnDtlMapper.selectList(asnDtlQueryWrapper);
                //获取收货仓库
				Warehouse warehouse = warehouseMapper.selectById(allAsnDtlList.get(0).getWhsId());
				//获取厂区
				String factoryCode = warehouse.getFacType();
				FacTypeEnum facTypeEnum = null;
				if(StringUtils.isBlank(factoryCode)){
					Shift.fatal("入库单对应的仓库没有维护厂区");
				}else{
					facTypeEnum = FacTypeEnum.getEnumByCode(factoryCode);
					if(facTypeEnum==null){
						Shift.fatal("入库单对应的仓区编码["+factoryCode+"]无法识别");
					}
				}


				// 必须满收的单据类型//
				if(Objects.equals(AsnTypeEnum.R20.code, asnHeader.getAsnType()) || Objects.equals(AsnTypeEnum.R19.code, asnHeader.getAsnType())) {
					BigDecimal orderQty = allAsnDtlList.stream().map(t -> t.getOrderQty()).reduce(BigDecimal.ZERO, BigDecimal::add);

					QueryWrapper<AsnDtlGoods> asnDtlGoodsQueryWrapper = new QueryWrapper<>();
					asnDtlGoodsQueryWrapper.in("ASN_DTL_ID", allAsnDtlList.stream().map(t -> t.getAsnDtlId()).collect(Collectors.toList()));
					List<AsnDtlGoods> asnDtlGoodsList = asnDtlGoodsMapper.selectList(asnDtlGoodsQueryWrapper);
					BigDecimal rcvQty = asnDtlGoodsList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);

					if(orderQty.compareTo(rcvQty) == 1) {
						Shift.fatal("必须满收才允许确认！");
					}
				}

				if (AsnTypeEnum.R14.code.equals(asnHeader.getAsnType())){
					BigDecimal orderQty = allAsnDtlList.stream().map(t -> t.getOrderQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
					QueryWrapper<AsnDtlGoods> asnDtlGoodsQueryWrapper = new QueryWrapper<>();
					asnDtlGoodsQueryWrapper.in("ASN_DTL_ID", allAsnDtlList.stream().map(t -> t.getAsnDtlId()).collect(Collectors.toList()));
					List<AsnDtlGoods> asnDtlGoodsList = asnDtlGoodsMapper.selectList(asnDtlGoodsQueryWrapper);
					BigDecimal rcvQty = asnDtlGoodsList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);

					if(orderQty.compareTo(rcvQty) == 1) {
						DataItemDetailDTO detailByPCodeAndName = dataItemDetailApi.getDataItemDetailByPCodeAndName("asn_pwd", "password");
						if (detailByPCodeAndName==null){
							Shift.fatal("请联系管理员输入刷卡密码!");
						}
						String pwd = detailByPCodeAndName.getItemValue();
						if (pwd==null){
							Shift.fatal("请联系管理员输入刷卡密码!");
						}
						if (dto.getPwd()==null){
							Shift.fatal("请输入密码!");
						}
						if (!pwd.equals(dto.getPwd())){
							Shift.fatal("密码错误");
						}
					}
				}

				// 是否需要创建送检单和待检回传
				boolean isCreateQmsIqc = (Objects.equals(AsnTypeEnum.R14.code, asnHeader.getAsnType()) || Objects.equals(AsnTypeEnum.R19.code, asnHeader.getAsnType()));

				// 收货单明细=》根据物料分组
				Map<Integer, List<AsnDtl>> skuGroup = allAsnDtlList.stream().collect(Collectors.groupingBy(t -> t.getSkuId(), Collectors.toList()));
				//定义MAP记录skuId和检验单号的关系
				Map<Integer,String> skuIqcMap = new HashMap<>();
				for (Integer skuId : skuGroup.keySet()) {
					List<AsnDtl> asnDtlList = skuGroup.get(skuId);

					// 收货单明细ID
					List<Integer> asnDtlIdList = asnDtlList.stream().map(t -> t.getAsnDtlId()).collect(Collectors.toList());

					// 收货单明细货品清单
					QueryWrapper<AsnDtlGoods> asnDtlGoodsQueryWrapper = new QueryWrapper<>();
					asnDtlGoodsQueryWrapper.in("ASN_DTL_ID", asnDtlIdList);
					List<AsnDtlGoods> asnDtlGoodsList = asnDtlGoodsMapper.selectList(asnDtlGoodsQueryWrapper);

					if(asnDtlGoodsList.size() > 0) {
						// 是否急料
						Integer isEmergency = isEmergencyMap.get(skuId);
						if (isEmergency == null) {
							isEmergency = 0;
						}

						// 物料
						Sku sku = skuMapper.selectById(skuId);

						// 当前物料的收货数
						BigDecimal skuQty = asnDtlGoodsList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);

						// 【创建送检单】
						QmsIqc qmsIqc = null;
						if(isCreateQmsIqc) {
							// 送检单号
							String oqcNo = basicSimpleCodeRuleApi.GenerateCode(IQC_INSP_ORDER_NO);
							qmsIqc = new QmsIqc();
							qmsIqc.setOqc(oqcNo); 						// 送检单号
							qmsIqc.setProductId(sku.getSkuId()); 		// 物料ID
							qmsIqc.setProductCode(sku.getSkuCode()); 	// 物料编码
							qmsIqc.setProductName(sku.getDescCn()); 	// 物料描述
							qmsIqc.setSubmitInspQty(skuQty); 			// 送检数量
							qmsIqc.setSubmitInspMode(Integer.parseInt(inspMode.getItemValue())); 		// 送检方式ID
							qmsIqc.setInspModeId(Integer.parseInt(inspMode.getItemValue())); 			// 检验方式ID
							qmsIqc.setInspModeCode(inspMode.getRemark()); 								// 检验方式编码
							qmsIqc.setInspStdType(Integer.parseInt(INSPECTION_GROUP_TYPE)); 			// 检验类型
							qmsIqc.setInspectionStatus(QmsOqcStatusEnum.WAITING_FOR_CHECK.getCode()); 	// 待报检
							qmsIqc.setDeliveryNo(asnHeader.getAsnNo()); 		// 送货单号
							qmsIqc.setIsEmergency(isEmergency); 				// 是否急料
							qmsIqc.setVendorId(vendor.getVendorId()); 			// 供应商ID
							qmsIqc.setVendorCode(vendor.getVendorCode()); 		// 供应商编码
							qmsIqc.setInspectionTime(date); 					// 报检时间
							qmsIqc.setInspectionPerson(loginName); 				// 报检人
							qmsIqc.setCreateUser(loginName);
							qmsIqc.setCreateTime(date);

							qmsIqc.setFactory(facTypeEnum.getEnumName());//工厂
                            if(StringUtils.isEmpty(sku.getSkuTypeCode())){
                            	Shift.fatal("没有查到物料【"+sku.getSkuCode()+"】的采购类型");
							}
							//查找检验组
							InspectionGroupStaffDto inspectionGroup = inspectionGroupApi.getInspectionGroupBySkuTypeAndGroupType(sku.getSkuTypeCode(), INSPECTION_GROUP_TYPE);

		 					//InspectionGroupStaffDto inspectionGroup = inspectionGroupApi.getInspectionGroupSkuListBySkuId(sku.getSkuId(), INSPECTION_GROUP_TYPE);
							if (inspectionGroup == null || inspectionGroup.getInspectionGroupId() == null) {
								Shift.fatal(String.format("物料[%s]的来料检验组没有配置！", sku.getSkuCode()));
							}
							//查找检验组的检验员带上工厂条件
							List<InspectionGroupStaffDto> inspectionGroupStaffList = inspectionGroupApi.selectByInspectionGroupIdStaffFactoryDefault(inspectionGroup.getInspectionGroupId(),facTypeEnum.getEnumName(), 1);
							if (inspectionGroupStaffList == null || inspectionGroupStaffList.size() == 0) {
								inspectionGroupStaffList = inspectionGroupApi.selectByInspectionGroupIdStaffDefault(inspectionGroup.getInspectionGroupId(), 0);
							}
							if (inspectionGroupStaffList == null || inspectionGroupStaffList.size() == 0) {
								Shift.fatal(String.format("物料[%s]的来料检验组没有配置默认检验员！", sku.getSkuCode()));
							}
							InspectionGroupStaffDto inspectionGroupStaffDto = inspectionGroupStaffList.get(0);
							qmsIqc.setCheckerId(inspectionGroupStaffDto.getStaffId()); 					// 检验人ID
							qmsIqc.setIsWithoutCheck(0); 												// 不免检
							qmsIqc.setStatus(QmsOqcStatusEnum.CHECK_WAIT_FOR_INSPECTION.getCode()); 	// 待检

					/*// 查找是否免检，后面根据业务需要再加，目前SAP没有免检回传的相应的接口
					if (vendor.getVendorCode() == null) {
						qmsIqc.setIsWithoutCheck(0); 												// 不免检
						qmsIqc.setStatus(QmsOqcStatusEnum.CHECK_WAIT_FOR_INSPECTION.getCode()); 	// 待检
					} else {
						InspectionListDto inspectionListDto = inspectionListApi.selectByMaterialCode(sku.getSkuCode(), vendor.getVendorCode());
						if (inspectionListDto == null || inspectionListDto.getInspectionListId() == null) {
							qmsIqc.setIsWithoutCheck(0); 											// 不免检
							qmsIqc.setStatus(QmsOqcStatusEnum.CHECK_WAIT_FOR_INSPECTION.getCode()); // 待检
						} else {
							qmsIqc.setIsWithoutCheck(1); 								// 免检
							qmsIqc.setStatus(QmsOqcStatusEnum.CHECK_ACCESS.getCode()); 	// 合格
						}//
					}*/

							qmsIqcMapper.insert(qmsIqc);
							qmsIqcList.add(qmsIqc);
							skuIqcMap.put(skuId,oqcNo);
						}


						// 处理收货单明细
						for (AsnDtl asnDtl : asnDtlList) {
							asnDtlGoodsQueryWrapper.clear();
							asnDtlGoodsQueryWrapper.eq("ASN_DTL_ID", asnDtl.getAsnDtlId());
							asnDtlGoodsList = asnDtlGoodsMapper.selectList(asnDtlGoodsQueryWrapper);

							if(asnDtlGoodsList.size() > 0) {
								// 预收数量
								BigDecimal qty = asnDtlGoodsList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
								if(isCreateQmsIqc) {
									//查询仓库
									String lgort = mappingHouseService.getSapHouseByWhsId(asnDtl.getWhsId(), asnHeader.getFactory());

									// 【回传SAP实体类】
									ZDT_064_ReqRECORDS record = new ZDT_064_ReqRECORDS();
									//加个后缀 防止和成品重复
									record.setWMSID(asnDtl.getAsnDtlId() + "RAW");    			// WMSID传收货单明细ID
									record.setBUDAT(DateUtils.format(date, "yyyyMMdd"));
									record.setMATNR(sku.getSkuCode());                    	// 转换物料
									// 数量
									record.setLGORT(lgort);									// 转换仓库

									// 根据不同单据类型设置不同值1：送货单；2：采购订单：3:交货单
									log.info("单据类型===》" + asnHeader.getAsnType());
									if (AsnTypeEnum.R14.code.equals(asnHeader.getAsnType())) {
										// 送货单
										record.setBILLTYPE("1");
										record.setSTREAMNO(asnDtl.getAsnNo());
										record.setSTREAMITEM(asnDtl.getAsnLineNo());	// 同步的时候没有生成内部行号
										record.setMENGE(qty.toString());
									} else if (AsnTypeEnum.R19.code.equals(asnHeader.getAsnType())) {
										// 交货单
										record.setBILLTYPE("3");
										record.setMENGE(asnDtl.getOrderQty()+"");//公司间交货取订单数量，走冲销接口冲销
										if (asnDtl.getAsnNo().indexOf("R19") ==0 ) { 	// 自己创建的单号，取来源单号和行号
											record.setVBELN(asnDtl.getSourceNo());
											record.setPOSNR(asnDtl.getSourceLineNo());
										} else {
											record.setVBELN(asnDtl.getAsnNo());
											record.setPOSNR(asnDtl.getAsnLineNo());
										}
									}
									//多增加回传检验批(iqc单号+"-"+asnDtlId)
									ZDT_Reserve rsv1 = new ZDT_Reserve();
									String iqcBatch = skuIqcMap.get(skuId)+"-"+asnDtl.getAsnDtlId();
									rsv1.setRsv1(iqcBatch);
									record.setRSV1(rsv1);
									sapReturnList.add(record);	// 添加到待回传
									//更新udf4字段 保存检验批
									asnDtlMapper.updateUdf4ById(asnDtl.getAsnDtlId(),iqcBatch);
								}


								// 【入库凭证--单头】
								TrsnHeader trsnHeader = new TrsnHeader();
								trsnHeader.setNoteType(TrsnNoteTypeEnum.IN_STORAGE.getCode());
								trsnHeader.setStatus(TrsnHeaderStatusEnum.CMP.code);
								trsnHeader.setNoteNo(basicSimpleCodeRuleApi.GenerateCode(TRSN_ORDER));
								trsnHeader.setOwner(asnHeader.getOwner());
								trsnHeader.setFactory(asnHeader.getFactory());
								trsnHeader.setVendorId(asnHeader.getVendorId());
								trsnHeader.setFmDoc(asnHeader.getAsnNo());
								trsnHeader.setWhsId(asnDtl.getWhsId());
								trsnHeader.setCreateUser(loginName);
								trsnHeader.setCreateTime(date);
								trsnHeaderMapper.insert(trsnHeader);

								// 【入库凭证--明细】
								TrsnDtl trsnDtl = new TrsnDtl();
								trsnDtl.setNoteLineNo("1");
								trsnDtl.setInvUpdateFlag(TrsnDtlInvUpdateFlagEnum.IN.code);
								trsnDtl.setStatus(TrsnDtlStatusEnum.CMP.code);
								trsnDtl.setUnit(asnDtl.getUnit());
								trsnDtl.setSkuId(asnDtl.getSkuId());
								trsnDtl.setQty(qty);
								trsnDtl.setFmDoc(asnHeader.getAsnNo());
								trsnDtl.setQaStatus(asnDtl.getQaStatus());
								trsnDtl.setFmDocLine(asnDtl.getAsnLineNo());
								trsnDtl.setNoteNo(trsnHeader.getNoteNo());
								trsnDtl.setTrsnHeaderId(trsnHeader.getTrsnHeaderId());
								trsnDtl.setCreateUser(loginName);
								trsnDtl.setCreateTime(date);
								Class<?> asnDtlClass = asnDtl.getClass();
								Class<?> trsnDtlClass = trsnDtl.getClass();
								for (int i = 1; i < 13; i++) {
									Field field = asnDtlClass.getDeclaredField("lotAttr" + i);
									Method method = trsnDtlClass.getMethod("setLotAttr" + i, String.class);
									field.setAccessible(true);
									method.setAccessible(true);
									method.invoke(trsnDtl, field.get(asnDtl));
								}
								trsnDtlMapper.insert(trsnDtl);

								// 【更新收货单明细】
								asnDtl.setRcvTime(date); 				// (收货时间)=系统当前时间
								asnDtl.setPutawayFlag(1); 				// (上架标识)=1(需要上架)
								asnDtl.setPutawayStatus(0); 			// (上架状态)=0(未上架)
								asnDtl.setStatus(AsnDtlStatusEnum.FINISH.code);
								asnDtl.setModifyUser(loginName);
								asnDtl.setModifyTime(date);
								asnDtl.setQcStatus(isCreateQmsIqc ? QcStatusEnum.已创建质检单.getCode() : QcStatusEnum.未创建质检单.getCode());
								asnDtl.setInspNo(isCreateQmsIqc ? qmsIqc.getOqc() : null);
								asnDtlMapper.updateById(asnDtl);

								// 【更新收货单明细的数量】
								UpdateAsnDtlQtyReceiveRequest updateAsnDtlQtyReceiveRequest = new UpdateAsnDtlQtyReceiveRequest();
								updateAsnDtlQtyReceiveRequest.setAsnDtlId(asnDtl.getAsnDtlId());
								updateAsnDtlQtyReceiveRequest.setRcvQty(qty);
								updateAsnDtlQtyReceiveRequest.setRcvQtyEa(qty);
								asnDtlMapper.updateQtyById(updateAsnDtlQtyReceiveRequest);

								// 【遍历处理每个收货单的每个货品清单goods】
								for (AsnDtlGoods asnDtlGoods : asnDtlGoodsList) {
									Goods goods = goodsMapper.selectById(asnDtlGoods.getGoodsId());
									if(!goodsItemMap.containsKey(goods.getGoodsId())) {
										goodsItemMap.put(goods.getGoodsId(), goods);

										// 【更新goods】
										String oldGoodsJson = JSON.toJSONString(goods); // 原先的json
										goods.setWhsId(asnDtl.getWhsId());
										goods.setStatus(GoodsStatusEnum.WAIT_UP.code);	// 待上架
										goods.setModifyUser(loginName);
										goods.setModifyTime(date);
										goods.setStockInDate(date);
										String newGoodsJson = JSON.toJSONString(goods); // 更新后的json
										goodsMapper.updateById(goods);

										// 【新增goods日志】
										GoodsLog goodsLog = new GoodsLog();
										goodsLog.setGoodsSn(goods.getGoodsSn());
										goodsLog.setOpCode(OpCodeEnum.RECEIVE.getCode());
										goodsLog.setReason(OpCodeEnum.RECEIVE.getEnumName());
										goodsLog.setOperator(OpCodeEnum.RECEIVE.getEnumName());
										goodsLog.setUpdateContent("未更新的:" + oldGoodsJson + ",更新的:" + newGoodsJson);
										goodsLog.setCreateUser(loginName);
										goodsLog.setCreateTime(date);
										goodsLogMapper.insert(goodsLog);

										if(isCreateQmsIqc) {
											// 【创建检验单送检产品明细】
											QmsOqcRcard qmsOqcRcard = new QmsOqcRcard();
											qmsOqcRcard.setOqcId(qmsIqc.getOqcId());
											qmsOqcRcard.setOqc(qmsIqc.getOqc());
											qmsOqcRcard.setRcardNo(goods.getGoodsSn());
											qmsOqcRcard.setCreateUser(loginName);
											qmsOqcRcard.setCreateTime(date);
											qmsOqcRcardMapper.insert(qmsOqcRcard);
										}
									}

									// 【入库凭证--明细goods】
									TrsnDtlGoods trsnDtlGoods = new TrsnDtlGoods();
									trsnDtlGoods.setTrsnDtlId(trsnDtl.getTrsnDtlId());
									trsnDtlGoods.setGoodsSn(goods.getGoodsSn());
									trsnDtlGoods.setGoodsId(goods.getGoodsId());
									trsnDtlGoods.setQty(asnDtlGoods.getQty());
									trsnDtlGoods.setQaStatus(goods.getQaStatus());
									trsnDtlGoods.setStatus(TransferDtlGoodStatusEnum.HAS_RECEIVE.code);
									trsnDtlGoods.setCreateTime(date);
									trsnDtlGoods.setCreateUser(loginName);
									trsnDtlGoodsMapper.insert(trsnDtlGoods);

									// 【更新收货单明细货品清单(wms_asn_dtl_goods)】
									asnDtlGoods.setStatus(AsnDtlGoodsStatusEnum.HAS_RECEIVE.getCode());
									asnDtlGoods.setModifyUser(loginName);
									asnDtlGoods.setModifyTime(date);
									asnDtlGoodsMapper.updateById(asnDtlGoods);
								}
							} else {
								// 明细预收 = 0
								asnDtl.setRcvTime(date); 			// (收货时间)=系统当前时间
								asnDtl.setPutawayFlag(0); 			// (上架标识)=0(不需要上架)
								asnDtl.setPutawayStatus(0); 		// (上架状态)=0(未上架)
								asnDtl.setStatus(AsnDtlStatusEnum.FINISH.code);
								asnDtl.setQcStatus(QcStatusEnum.未创建质检单.getCode());
								asnDtl.setModifyUser(loginName);
								asnDtl.setModifyTime(date);
								asnDtlMapper.updateById(asnDtl);
							}
						}
					} else {
						// 物料预收 = 0
						for (AsnDtl asnDtl : asnDtlList) {
							asnDtl.setRcvTime(date); 			// (收货时间)=系统当前时间
							asnDtl.setPutawayFlag(0); 			// (上架标识)=0(不需要上架)
							asnDtl.setPutawayStatus(0); 		// (上架状态)=0(未上架)
							asnDtl.setStatus(AsnDtlStatusEnum.FINISH.code);
							asnDtl.setQcStatus(QcStatusEnum.未创建质检单.getCode());
							asnDtl.setModifyUser(loginName);
							asnDtl.setModifyTime(date);
							asnDtlMapper.updateById(asnDtl);
						}
					}
				}

				// 【更新库存】
				Map<String, List<Goods>> goodsMap = goodsItemMap.values().stream().collect(Collectors.groupingBy(t ->
						(t.getWhsId() + "#" + t.getLocId() + "#" + t.getOwner() + "#" +
								t.getSkuId() + "#" + t.getFactory() + "#" + t.getVendorId() + "#" +
								t.getLotno() + "#" + t.getInvAttr() + "#" + t.getQaStatus() + "#"), Collectors.toList()));
				for (String goodsKey : goodsMap.keySet()) {
					List<Goods> goodsInvList = goodsMap.get(goodsKey);
					Goods goodsInv = goodsInvList.get(0);
					BigDecimal goodsQty = goodsInvList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);

					UpdateInventoryInputDto input = new UpdateInventoryInputDto();
					input.setWhsId(goodsInv.getWhsId());			// 仓库
					input.setOwner(goodsInv.getOwner());			// 货主
					input.setSkuId(goodsInv.getSkuId());			// 物料
					input.setFactory(goodsInv.getFactory());		// 组织
					input.setVendorId(goodsInv.getVendorId());		// 供应商
					input.setInvAttr(goodsInv.getInvAttr());		// 库存性质
					input.setQaStatus(goodsInv.getQaStatus());		// QA状态
					input.setUnit(goodsInv.getUnit());				// 单位
					input.setQty(goodsQty);
					input.setOperator(loginName);
					inventoryService.updateLocInventroy(input);
					inventoryService.updateZoneInventory(input);
				}

				// 【更新收货单状态】
				asnHeader.setModifyUser(loginName);
				asnHeader.setModifyTime(date);
				asnHeader.setDeliveryTime(date);
				asnHeader.setToBusinessMan(loginName);
				asnHeader.setActualarrivetime(date);
				asnHeader.setStatus(AsnHeaderStatusEnum.FINISH.code);
				if (qmsIqcList.size() > 0) {
					asnHeader.setQcStatus(QcStatusEnum.已创建质检单.getCode());
				} else {
					asnHeader.setQcStatus(QcStatusEnum.未创建质检单.getCode());
				}
				asnHeaderMapper.updateById(asnHeader);

        /*
            调用SAP接口
            1：内销售后领料单；D14
			2：申购出库单：D15
			3:交货出库单
			4、报废出库单冻结
			4.1 报废单出库单过账 D16
			5、不同库位调拨
			6、工厂间调拨
			7、在途调拨
			8、标准委外领料出库D12
			9、标准委外退本厂
        */
				try {
					switch (AsnTypeEnum.getEnumByCode(asnHeader.getAsnType())) {
						case R11:
							getAndReturnMaterialBackService.getAndReturnMaterialBack(asnHeader,allAsnDtlList);
							break;
						case R12:
							outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"9");
							break;
						case R14:
							waitCheckBackService.backToSapSync(sapReturnList,asnHeader.getAsnNo());
							break;
						case R15:
							outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"3");
							break;
				/*case R16:
					outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"5");
					break;*/
						case R17:
							outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"1");
							break;
						case R18:
							outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"2");
							break;
						case R19:
							//临时更改 暂时不用调用冲销接口
							//deliveryWriteOffService.deliveryWriteOffWriteBack(asnHeader,allAsnDtlList);
							waitCheckBackService.backToSapSync(sapReturnList,asnHeader.getAsnNo());
							break;
						case R20:
							outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"3");
							break;
						case R21:
							outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"7");
							break;
						case R22:
							outStoreBackService.outStoreAsnWriteBack(asnHeader,allAsnDtlList,"5");
							break;
					}
				} catch (SystemException e) {
					Shift.fatal(e.getMessage());
				} catch (Exception e) {
					e.printStackTrace();
					Shift.fatal("回传SAP失败！");
				}
			}catch (Exception e){
				e.printStackTrace();
				throw e;
			}finally {
				//释放锁
				redisService.unlock(lockKey);
			}
		}
		return new Result<>();
	}

/*	private void waitCheckBack(List<ZDT_064_ReqRECORDS> sapReturnList, List<AsnDtl> allAsnDtlList) throws RemoteException {
		Map<String, String> sapBackMap = waitCheckBackService.backToSap(sapReturnList);
		for (AsnDtl item : allAsnDtlList) {
			String sapBackId = sapBackMap.get(item.getAsnDtlId() + "RAW");
			if (sapBackId != null) {
				//更新返回的库存凭证到明细表
				asnDtlMapper.updateUdf4ById(item.getAsnDtlId(), sapBackId);
			}
		}
	}*/


	/**
	 * 单例手工回传SAP
	 *
	 * @param asnHeaderId
	 * @throws RemoteException
	 */
	/*@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void test(Integer asnHeaderId) throws RemoteException {
		AsnHeader asnHeader = asnHeaderMapper.selectById(asnHeaderId);
		
		QueryWrapper<AsnDtl> asnDtlQueryWrapper = new QueryWrapper<>();
		asnDtlQueryWrapper.eq("ASN_HEADER_ID", asnHeader.getAsnHeaderId());
		List<AsnDtl> asnDtlList = asnDtlMapper.selectList(asnDtlQueryWrapper);
		
		List<ZDT_064_ReqRECORDS> sapReturnList = new ArrayList<>();
		
		Date date = new Date();
		
    	for (AsnDtl asnDtl : asnDtlList) {
    		// 物料
			Sku sku = skuMapper.selectById(asnDtl.getSkuId());
			
    		QueryWrapper<AsnDtlGoods> asnDtlGoodsQueryWrapper = new QueryWrapper<>();
			asnDtlGoodsQueryWrapper.eq("ASN_DTL_ID", asnDtl.getAsnDtlId());
			List<AsnDtlGoods> asnDtlGoodsList = asnDtlGoodsMapper.selectList(asnDtlGoodsQueryWrapper);

			if(asnDtlGoodsList.size() > 0) {
				// 预收数量
				BigDecimal qty = asnDtlGoodsList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
			
				// 【回传SAP实体类】
				ZDT_064_ReqRECORDS record = new ZDT_064_ReqRECORDS();
				record.setWMSID(asnDtl.getAsnDtlId() + "");    // WMSID传收货单明细ID
				record.setBUDAT(DateUtils.format(date, "yyyyMMdd"));
				record.setMATNR(sku.getSkuCode());                    // 转换物料
				record.setMENGE(qty + "");                            // 数量
				// 查询仓库
				String lgort = mappingHouseService.getSapHouseByWhsId(asnDtl.getWhsId(), asnHeader.getFactory());
				record.setLGORT(lgort);// 转换仓库
				// 根据不同单据类型设置不同值1：送货单；2：采购订单：3:交货单
				log.info("单据类型===》" + asnHeader.getAsnType());
				if (AsnTypeEnum.R14.code.equals(asnHeader.getAsnType())) {
					record.setBILLTYPE("1");						//送货单
					record.setSTREAMNO(asnHeader.getAsnNo());
					record.setSTREAMITEM(asnDtl.getAsnLineNo());	//同步的时候没有生成内部行号
					
				} else if (AsnTypeEnum.R19.code.equals(asnHeader.getAsnType())) {
					record.setBILLTYPE("3");						// 交货单
					if ("ASN".indexOf(asnHeader.getAsnNo()) >= 0) {	// 自己创建的单号，取来源单号和行号
						record.setEBELN(asnHeader.getSourceNo());
						record.setPOSNR(asnDtl.getSourceLineNo());
					} else {
						record.setEBELN(asnHeader.getAsnNo());
						record.setPOSNR(asnDtl.getAsnLineNo());
					}
				}
				sapReturnList.add(record);// 添加到待回传
			}
    	}
    	
    	HashMap<String, String> sapBackMap = waitCheckBackService.backToSap(sapReturnList);
		for (AsnDtl item : asnDtlList) {
			String sapBackId = sapBackMap.get(item.getAsnDtlId() + "");
			if (sapBackId != null) {
				//更新返回的库存凭证到明细表
				asnDtlMapper.updateUdf4ById(item.getAsnDtlId(), sapBackId);
			}
		}
	}*/
}
